home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume20 / rc / part04 < prev    next >
Encoding:
Text File  |  1991-05-22  |  41.9 KB  |  1,588 lines

  1. Newsgroups: comp.sources.misc
  2. From: Byron Rakitzis <byron@archone.tamu.edu>
  3. Subject:  v20i013:  rc - A Plan 9 shell reimplementation, Part04/04
  4. Message-ID: <1991May22.154344.3314@sparky.IMD.Sterling.COM>
  5. Date: Wed, 22 May 1991 15:43:44 GMT
  6. Approved: kent@sparky.imd.sterling.com
  7. X-Md4-Signature: 965dbe7396fbd6b4febb604341f4925a
  8.  
  9. Submitted-by: Byron Rakitzis <byron@archone.tamu.edu>
  10. Posting-number: Volume 20, Issue 13
  11. Archive-name: rc/part04
  12.  
  13. #! /bin/sh
  14. # This is a shell archive.  Remove anything before this line, then feed it
  15. # into a shell via "sh file" or similar.  To overwrite existing files,
  16. # type "sh file -c".
  17. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  18. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  19. # Contents:  COPYRIGHT Makefile builtins.h except.c except.h exec.c
  20. #   exec.h footobar.h glob.h glom.h heredoc.h input.h lex.h list.c
  21. #   list.h main.c match.c match.h mksignal nalloc.c nalloc.h node.h
  22. #   open.c open.h parse.h rc.h redir.h status.c status.h stddef.h
  23. #   stdlib.h string.h tree.h unistd.h utils.h version.c walk.h
  24. # Wrapped by kent@sparky on Wed May 22 01:21:49 1991
  25. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  26. echo If this archive is complete, you will see the following message:
  27. echo '          "shar: End of archive 4 (of 4)."'
  28. if test -f 'COPYRIGHT' -a "${1}" != "-c" ; then 
  29.   echo shar: Will not clobber existing file \"'COPYRIGHT'\"
  30. else
  31.   echo shar: Extracting \"'COPYRIGHT'\" \(1106 characters\)
  32.   sed "s/^X//" >'COPYRIGHT' <<'END_OF_FILE'
  33. X/*
  34. X * Copyright 1991 Byron Rakitzis.  All rights reserved.
  35. X *
  36. X * This software is not subject to any license of the American Telephone
  37. X * and Telegraph Company or of the Regents of the University of California.
  38. X *
  39. X * Permission is granted to anyone to use this software for any purpose on
  40. X * any computer system, and to alter it and redistribute it freely, subject
  41. X * to the following restrictions:
  42. X *
  43. X * 1. The author is not responsible for the consequences of use of this
  44. X *    software, no matter how awful, even if they arise from flaws in it.
  45. X *
  46. X * 2. The origin of this software must not be misrepresented, either by
  47. X *    explicit claim or by omission.  Since few users ever read sources,
  48. X *    credits must appear in the documentation.
  49. X *
  50. X * 3. Altered versions must be plainly marked as such, and must not be
  51. X *    misrepresented as being the original software.  Since few users
  52. X *    ever read sources, credits must appear in the documentation.
  53. X *
  54. X * 4. This notice may not be removed or altered.
  55. X *
  56. X *    [this copyright notice is adapted from Henry Spencer's
  57. X *    "awf" copyright notice.]
  58. X */
  59. END_OF_FILE
  60.   if test 1106 -ne `wc -c <'COPYRIGHT'`; then
  61.     echo shar: \"'COPYRIGHT'\" unpacked with wrong size!
  62.   fi
  63.   # end of 'COPYRIGHT'
  64. fi
  65. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  66.   echo shar: Will not clobber existing file \"'Makefile'\"
  67. else
  68.   echo shar: Extracting \"'Makefile'\" \(1518 characters\)
  69.   sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  70. X# Makefile for rc.
  71. X#
  72. X# Define the macro NODIRENT if your system has <sys/dir.h> but not <dirent.h>.
  73. X# Define the macro NONMPIPES if your system does not support named pipes.
  74. X# Define the macro NOJOB if your system does not support job control.
  75. X# Define the macro NOLIMITS if your system does not support Berkeley limits.
  76. X# Define the macro READLINE if you want rc to call GNU readline instead of read(2).
  77. X
  78. X# Get rid of default CFLAGS on braindamaged make's.
  79. XCFLAGS=
  80. X
  81. X# Use an ANSI compiler (or at least one that groks prototypes and void *):
  82. XCC=gcc -g -O
  83. X
  84. X# On an sgi running IRIX 3.3.1 I used:
  85. X#CC=cc -g -O
  86. X#
  87. X# On the NeXT I used
  88. X#CC=cc -g -O -DNODIRENT
  89. X#
  90. X# On a VAX running BSD 4.2
  91. X#CC=gcc -g -O -DNODIRENT
  92. X
  93. X# Use bison if you will, but yacc generates a smaller y.tab.c, and the speed
  94. X# of the parser is largely irrelevant in a shell.
  95. XYACC=yacc
  96. X
  97. XOBJS =  builtins.o except.o exec.o fn.o footobar.o glob.o glom.o hash.o heredoc.o \
  98. X    input.o lex.o list.o main.o match.o nalloc.o open.o redir.o sigmsgs.o status.o \
  99. X    tree.o utils.o var.o version.o walk.o which.o y.tab.o
  100. X
  101. X# If rc is compiled with GNU readline, you must supply the correct arguments to
  102. X# ld on this line. Typically this would be something like:
  103. X#
  104. X#    $(CC) -o rc $(OBJS) -lreadline -ltermcap
  105. X
  106. Xrc: $(OBJS)
  107. X    $(CC) -o rc $(OBJS)
  108. X
  109. Xsigmsgs.c : mksignal
  110. X    sh mksignal /usr/include/sys/signal.h
  111. X
  112. Xy.tab.c: parse.y
  113. X    $(YACC) -d parse.y
  114. X
  115. Xclean:
  116. X    rm -f *.o *.tab.[ch] sigmsgs.[ch]
  117. X
  118. X# dependencies:
  119. X
  120. Xsigmsgs.h : sigmsgs.c
  121. Xlex.o y.tab.o: y.tab.c
  122. Xfn.c status.c: sigmsgs.h
  123. END_OF_FILE
  124.   if test 1518 -ne `wc -c <'Makefile'`; then
  125.     echo shar: \"'Makefile'\" unpacked with wrong size!
  126.   fi
  127.   # end of 'Makefile'
  128. fi
  129. if test -f 'builtins.h' -a "${1}" != "-c" ; then 
  130.   echo shar: Will not clobber existing file \"'builtins.h'\"
  131. else
  132.   echo shar: Extracting \"'builtins.h'\" \(162 characters\)
  133.   sed "s/^X//" >'builtins.h' <<'END_OF_FILE'
  134. Xtypedef void builtin_t(char **);
  135. X
  136. Xextern builtin_t *isbuiltin(char *);
  137. Xextern void b_exec(char **), funcall(char **), b_dot(char **);
  138. Xextern char *which(char *);
  139. END_OF_FILE
  140.   if test 162 -ne `wc -c <'builtins.h'`; then
  141.     echo shar: \"'builtins.h'\" unpacked with wrong size!
  142.   fi
  143.   # end of 'builtins.h'
  144. fi
  145. if test -f 'except.c' -a "${1}" != "-c" ; then 
  146.   echo shar: Will not clobber existing file \"'except.c'\"
  147. else
  148.   echo shar: Extracting \"'except.c'\" \(2296 characters\)
  149.   sed "s/^X//" >'except.c' <<'END_OF_FILE'
  150. X#include <setjmp.h>
  151. X#include <stdarg.h>
  152. X#include "rc.h"
  153. X#include "utils.h"
  154. X#include "except.h"
  155. X#include "status.h"
  156. X#include "hash.h"
  157. X#include "input.h"
  158. X#include "nalloc.h"
  159. X
  160. X/*
  161. X   a return goes back stack frames to the last return. A break does not. A signal
  162. X   goes to the last interactive level.
  163. X*/
  164. X
  165. Xstatic Estack *estack;
  166. X
  167. X/* add an exception to the input stack. */
  168. X
  169. Xvoid except(enum except e, jmp_buf jb, Estack *ex) {
  170. X    ex->prev = estack;
  171. X    estack = ex;
  172. X
  173. X    switch (estack->e = e) {
  174. X    case ARENA:
  175. X        estack->b = newblock();
  176. X        break;
  177. X    case ERROR: case BREAK: case RETURN:
  178. X        estack->interactive = interactive;
  179. X        estack->jb = (jmp_buf *) jb;
  180. X        break;
  181. X    case STAR:
  182. X        break;
  183. X    }
  184. X}
  185. X
  186. X/* remove an exception, restore last interactive value */
  187. X
  188. Xvoid unexcept(void) {
  189. X    if (estack->e == ERROR)
  190. X        interactive = estack->interactive;
  191. X    else if (estack->e == ARENA)
  192. X        restoreblock(estack->b);
  193. X    estack = estack->prev;
  194. X}
  195. X
  196. X/*
  197. X   Raise an exception. The rules are pretty complicated: you can return from a loop inside a
  198. X   function, but you can't break from a function inside of a loop. On errors, rc_raise() goes back
  199. X   to the LAST INTERACTIVE stack frame. If no such frame exists, then rc_raise() exits the shell.
  200. X   This is what happens, say, when there is a syntax error in a noninteractive shell script. While
  201. X   traversing the exception stack backwards, rc_raise() also removes input sources (closing
  202. X   file-descriptors, etc.) and pops instances of $* that have been pushed onto the variable stack
  203. X   (e.g., for a function call).
  204. X*/
  205. X
  206. Xvoid rc_raise(enum except e) {
  207. X    if (e == ERROR && rc_pid != getpid())
  208. X            exit(1); /* child processes exit on an error/signal */
  209. X
  210. X    for (; estack != NULL; estack = estack->prev)
  211. X        if (estack->e != e) {
  212. X            if (e == BREAK && estack->e != ARENA)
  213. X                rc_error("break outside of loop");
  214. X            else if (e == RETURN && estack->e == ERROR) /* can return from loops inside functions */
  215. X                rc_error("return outside of function");
  216. X            if (estack->e == STAR)
  217. X                varrm("*", TRUE);
  218. X            else if (estack->e == ARENA)
  219. X                restoreblock(estack->b);
  220. X        } else {
  221. X            if (e == ERROR && !estack->interactive) {
  222. X                popinput();
  223. X            } else {
  224. X                jmp_buf *j = estack->jb;
  225. X
  226. X                interactive = estack->interactive;
  227. X                estack = estack->prev;
  228. X                longjmp(*j, 1);
  229. X            }
  230. X        }
  231. X    rc_exit(1); /* top of exception stack */
  232. X}
  233. END_OF_FILE
  234.   if test 2296 -ne `wc -c <'except.c'`; then
  235.     echo shar: \"'except.c'\" unpacked with wrong size!
  236.   fi
  237.   # end of 'except.c'
  238. fi
  239. if test -f 'except.h' -a "${1}" != "-c" ; then 
  240.   echo shar: Will not clobber existing file \"'except.h'\"
  241. else
  242.   echo shar: Extracting \"'except.h'\" \(295 characters\)
  243.   sed "s/^X//" >'except.h' <<'END_OF_FILE'
  244. Xenum except { ERROR, BREAK, RETURN, STAR, ARENA };
  245. Xtypedef struct Estack Estack;
  246. X
  247. Xstruct Estack {
  248. X    enum except e;
  249. X    boolean interactive;
  250. X    jmp_buf *jb;
  251. X    Block *b;
  252. X    Estack *prev;
  253. X};
  254. X
  255. Xextern void rc_raise(enum except);
  256. Xextern void except(enum except, jmp_buf, Estack *);
  257. Xextern void unexcept(void);
  258. END_OF_FILE
  259.   if test 295 -ne `wc -c <'except.h'`; then
  260.     echo shar: \"'except.h'\" unpacked with wrong size!
  261.   fi
  262.   # end of 'except.h'
  263. fi
  264. if test -f 'exec.c' -a "${1}" != "-c" ; then 
  265.   echo shar: Will not clobber existing file \"'exec.c'\"
  266. else
  267.   echo shar: Extracting \"'exec.c'\" \(2186 characters\)
  268.   sed "s/^X//" >'exec.c' <<'END_OF_FILE'
  269. X/*
  270. X   exec.c: exec() takes an argument list and does the appropriate thing
  271. X   (calls a builtin, calls a function, etc.)
  272. X*/
  273. X
  274. X#include <setjmp.h>
  275. X#include <signal.h>
  276. X#include "rc.h"
  277. X#include "utils.h"
  278. X#include "exec.h"
  279. X#include "status.h"
  280. X#include "hash.h"
  281. X#include "builtins.h"
  282. X#include "footobar.h"
  283. X#include "except.h"
  284. X#include "redir.h"
  285. X
  286. Xvoid exec(List *s, boolean parent) {
  287. X    char **av, **ev;
  288. X    int pid, stat;
  289. X    builtin_t *b;
  290. X    char *path = NULL;
  291. X    void (*handler)(int);
  292. X    boolean forked;
  293. X
  294. X    av = list2array(s, dashex);
  295. X    ev = makeenv();
  296. X
  297. Xagain:    if (*av == NULL    || isabsolute(*av)) /* null command or absolute pathname */
  298. X        b = NULL;
  299. X    else if (fnlookup(*av) != NULL)
  300. X        b = funcall;
  301. X    else
  302. X        b = isbuiltin(*av);
  303. X
  304. X    if (b == b_exec) {
  305. X        parent = FALSE;
  306. X        b(av++);
  307. X        if (*av == NULL)
  308. X            return; /* return on null exec */
  309. X        goto again;    /* go back and evaluate the type of command to be executed */
  310. X    }
  311. X
  312. X    if (b == NULL) {
  313. X        path = which(*av);
  314. X        if (path == NULL && *av != NULL) { /* perform null commands for redirections */
  315. X            fprint(2,"%s not found\n",*av);
  316. X            set(FALSE);
  317. X            redirq = NULL;
  318. X            empty_fifoq();
  319. X            if (parent)
  320. X                return;
  321. X            rc_exit(1);
  322. X        }
  323. X    }
  324. X
  325. X    /* if parent & the redirq is nonnull, builtin or not it has to fork. */
  326. X
  327. X    if (parent && (b == NULL || redirq != NULL)) {
  328. X        pid = fork();
  329. X        forked = TRUE;
  330. X    } else {
  331. X        pid = 0;
  332. X        forked = FALSE;
  333. X    }
  334. X
  335. X    switch (pid) {
  336. X    case -1:
  337. X        uerror("fork");
  338. X        rc_error(NULL);
  339. X        /* NOTREACHED */
  340. X    case 0:
  341. X        if (forked)
  342. X            setsigdefaults();
  343. X        doredirs();
  344. X
  345. X        /* null commands performed for redirections */
  346. X        if (*av == NULL || b != NULL) {
  347. X            if (b != NULL)
  348. X                b(av);
  349. X            empty_fifoq();
  350. X            if (!forked && parent)
  351. X                return;
  352. X            rc_exit(getstatus());
  353. X        }
  354. X        execve(path, (const char **) av, (const char **) ev); /* bogus, huh? */
  355. X        uerror(*av);
  356. X        rc_exit(1);
  357. X        /* NOTREACHED */
  358. X    default:
  359. X        if ((handler = signal(SIGINT, SIG_IGN)) != sig)
  360. X            signal(SIGINT, handler); /* don't ignore interrupts in noninteractive mode */
  361. X        while (pid != wait(&stat))
  362. X            if (pid < 0)
  363. X                uerror("wait");
  364. X        signal(SIGINT, handler);
  365. X        redirq = NULL;
  366. X        empty_fifoq();
  367. X        setstatus(stat);
  368. X        if (stat == SIGINT) /* interrupted? let the handler deal with it. */
  369. X            rc_raise(ERROR);
  370. X    }
  371. X}
  372. END_OF_FILE
  373.   if test 2186 -ne `wc -c <'exec.c'`; then
  374.     echo shar: \"'exec.c'\" unpacked with wrong size!
  375.   fi
  376.   # end of 'exec.c'
  377. fi
  378. if test -f 'exec.h' -a "${1}" != "-c" ; then 
  379.   echo shar: Will not clobber existing file \"'exec.h'\"
  380. else
  381.   echo shar: Extracting \"'exec.h'\" \(104 characters\)
  382.   sed "s/^X//" >'exec.h' <<'END_OF_FILE'
  383. Xstruct Rq {
  384. X    Node *r;
  385. X    struct Rq *n;
  386. X};
  387. X
  388. Xextern void exec(List *, boolean);
  389. Xextern void doredirs(void);
  390. END_OF_FILE
  391.   if test 104 -ne `wc -c <'exec.h'`; then
  392.     echo shar: \"'exec.h'\" unpacked with wrong size!
  393.   fi
  394.   # end of 'exec.h'
  395. fi
  396. if test -f 'footobar.h' -a "${1}" != "-c" ; then 
  397.   echo shar: Will not clobber existing file \"'footobar.h'\"
  398. else
  399.   echo shar: Extracting \"'footobar.h'\" \(258 characters\)
  400.   sed "s/^X//" >'footobar.h' <<'END_OF_FILE'
  401. Xextern char *fun2str(char *, Node *);
  402. Xextern char *ptree(Node *);
  403. Xextern char *list2str(char *, List *);
  404. Xextern char **list2array(List *, boolean);
  405. Xextern char *get_name(char *);
  406. Xextern List *parse_var(char *, char *);
  407. Xextern Node *parse_fn(char *, char *);
  408. END_OF_FILE
  409.   if test 258 -ne `wc -c <'footobar.h'`; then
  410.     echo shar: \"'footobar.h'\" unpacked with wrong size!
  411.   fi
  412.   # end of 'footobar.h'
  413. fi
  414. if test -f 'glob.h' -a "${1}" != "-c" ; then 
  415.   echo shar: Will not clobber existing file \"'glob.h'\"
  416. else
  417.   echo shar: Extracting \"'glob.h'\" \(66 characters\)
  418.   sed "s/^X//" >'glob.h' <<'END_OF_FILE'
  419. Xextern boolean lmatch(List *, List *);
  420. Xextern List *glob(List *);
  421. END_OF_FILE
  422.   if test 66 -ne `wc -c <'glob.h'`; then
  423.     echo shar: \"'glob.h'\" unpacked with wrong size!
  424.   fi
  425.   # end of 'glob.h'
  426. fi
  427. if test -f 'glom.h' -a "${1}" != "-c" ; then 
  428.   echo shar: Will not clobber existing file \"'glom.h'\"
  429. else
  430.   echo shar: Extracting \"'glom.h'\" \(275 characters\)
  431.   sed "s/^X//" >'glom.h' <<'END_OF_FILE'
  432. Xextern void assign(List *, List *, boolean);
  433. Xextern void qredir(Node *);
  434. Xextern List *append(List *, List*);
  435. Xextern List *flatten(List *);
  436. Xextern List *glom(Node *);
  437. Xextern List *concat(List *, List *);
  438. Xextern List *varsub(List *, List *);
  439. Xextern List *word(char *, char *);
  440. END_OF_FILE
  441.   if test 275 -ne `wc -c <'glom.h'`; then
  442.     echo shar: \"'glom.h'\" unpacked with wrong size!
  443.   fi
  444.   # end of 'glom.h'
  445. fi
  446. if test -f 'heredoc.h' -a "${1}" != "-c" ; then 
  447.   echo shar: Will not clobber existing file \"'heredoc.h'\"
  448. else
  449.   echo shar: Extracting \"'heredoc.h'\" \(99 characters\)
  450.   sed "s/^X//" >'heredoc.h' <<'END_OF_FILE'
  451. Xextern void heredoc(int);
  452. Xextern void qdoc(Node *, Node *);
  453. X
  454. Xtypedef struct Hq Hq;
  455. X
  456. Xextern Hq *hq;
  457. END_OF_FILE
  458.   if test 99 -ne `wc -c <'heredoc.h'`; then
  459.     echo shar: \"'heredoc.h'\" unpacked with wrong size!
  460.   fi
  461.   # end of 'heredoc.h'
  462. fi
  463. if test -f 'input.h' -a "${1}" != "-c" ; then 
  464.   echo shar: Will not clobber existing file \"'input.h'\"
  465. else
  466.   echo shar: Extracting \"'input.h'\" \(373 characters\)
  467.   sed "s/^X//" >'input.h' <<'END_OF_FILE'
  468. Xenum inputtype { FD, STRING };
  469. X
  470. X#define EOF (-1)
  471. X
  472. Xextern void initinput(void);
  473. Xextern Node *parseline(char *);
  474. Xextern int gchar(void);
  475. Xextern void ugchar(int);
  476. Xextern Node *doit(boolean);
  477. Xextern void flushu(void);
  478. Xextern void pushinput(int /*enum inputtype*/,...);
  479. Xextern void popinput(void);
  480. Xextern int last;
  481. X
  482. Xextern boolean rcrc;
  483. Xextern char *histstr;
  484. Xextern int histfd;
  485. END_OF_FILE
  486.   if test 373 -ne `wc -c <'input.h'`; then
  487.     echo shar: \"'input.h'\" unpacked with wrong size!
  488.   fi
  489.   # end of 'input.h'
  490. fi
  491. if test -f 'lex.h' -a "${1}" != "-c" ; then 
  492.   echo shar: Will not clobber existing file \"'lex.h'\"
  493. else
  494.   echo shar: Extracting \"'lex.h'\" \(502 characters\)
  495.   sed "s/^X//" >'lex.h' <<'END_OF_FILE'
  496. Xenum redirtype {
  497. X    FROM, CREATE, APPEND, HEREDOC, HERESTRING
  498. X};
  499. X
  500. Xtypedef struct Pipe {
  501. X    int left,right;
  502. X} Pipe;
  503. X
  504. Xtypedef struct Dup {
  505. X    enum redirtype type;
  506. X    int left,right;
  507. X} Dup;
  508. X
  509. Xtypedef struct Redir {
  510. X    enum redirtype type;
  511. X    int fd;
  512. X} Redir;
  513. X
  514. Xtypedef struct Word {
  515. X    char *w;
  516. X    char *m;
  517. X} Word;
  518. X
  519. Xextern int yylex(void);
  520. Xextern void inityy(void);
  521. Xextern void skipnl(void);
  522. Xextern void yyerror(const char *);
  523. Xextern void scanerror(char *);
  524. Xextern void print_prompt2(void);
  525. X
  526. Xextern const char nw[], dnw[];
  527. END_OF_FILE
  528.   if test 502 -ne `wc -c <'lex.h'`; then
  529.     echo shar: \"'lex.h'\" unpacked with wrong size!
  530.   fi
  531.   # end of 'lex.h'
  532. fi
  533. if test -f 'list.c' -a "${1}" != "-c" ; then 
  534.   echo shar: Will not clobber existing file \"'list.c'\"
  535. else
  536.   echo shar: Extracting \"'list.c'\" \(984 characters\)
  537.   sed "s/^X//" >'list.c' <<'END_OF_FILE'
  538. X/* list.c: routines for manipulating the List type */
  539. X
  540. X#include "rc.h"
  541. X#include "utils.h"
  542. X#include "list.h"
  543. X
  544. X/*
  545. X   These list routines assign meta values of null to the resulting lists;
  546. X   it is impossible to glob with the value of a variable unless this value
  547. X   is rescanned with eval---therefore it is safe to throw away the meta-ness
  548. X   of the list.
  549. X*/
  550. X
  551. X/* free a list from malloc space */
  552. X
  553. Xvoid listfree(List *p) {
  554. X    if (p == NULL)
  555. X        return;
  556. X    listfree(p->n);
  557. X    efree(p->w);
  558. X    efree(p);
  559. X}
  560. X
  561. X/* copy of list in malloc space (for storing a variable) */
  562. X
  563. XList *listcpy(List *s) {
  564. X    List *r;
  565. X
  566. X    if (s == NULL)
  567. X        return NULL;
  568. X
  569. X    r = enew(List);
  570. X    r->w = ecpy(s->w);
  571. X    r->m = NULL;
  572. X    r->n = listcpy(s->n);
  573. X
  574. X    return r;
  575. X}
  576. X
  577. X/* length of list */
  578. X
  579. XSIZE_T listlen(List *s) {
  580. X    SIZE_T size;
  581. X
  582. X    for (size = 0; s != NULL; s = s->n)
  583. X        size += strlen(s->w) + 1;
  584. X
  585. X    return size;
  586. X}
  587. X
  588. X/* number of elements in list */
  589. X
  590. Xint listnel(List *s) {
  591. X    int nel;
  592. X
  593. X    for (nel = 0; s != NULL; s = s->n)
  594. X        nel++;
  595. X
  596. X    return nel;
  597. X}
  598. END_OF_FILE
  599.   if test 984 -ne `wc -c <'list.c'`; then
  600.     echo shar: \"'list.c'\" unpacked with wrong size!
  601.   fi
  602.   # end of 'list.c'
  603. fi
  604. if test -f 'list.h' -a "${1}" != "-c" ; then 
  605.   echo shar: Will not clobber existing file \"'list.h'\"
  606. else
  607.   echo shar: Extracting \"'list.h'\" \(119 characters\)
  608.   sed "s/^X//" >'list.h' <<'END_OF_FILE'
  609. Xextern void listfree(List *);
  610. Xextern List *listcpy(List *);
  611. Xextern SIZE_T listlen(List *);
  612. Xextern int listnel(List *);
  613. END_OF_FILE
  614.   if test 119 -ne `wc -c <'list.h'`; then
  615.     echo shar: \"'list.h'\" unpacked with wrong size!
  616.   fi
  617.   # end of 'list.h'
  618. fi
  619. if test -f 'main.c' -a "${1}" != "-c" ; then 
  620.   echo shar: Will not clobber existing file \"'main.c'\"
  621. else
  622.   echo shar: Extracting \"'main.c'\" \(2456 characters\)
  623.   sed "s/^X//" >'main.c' <<'END_OF_FILE'
  624. X/* main.c: handles initialization of rc and command line options */
  625. X
  626. X#include <stdarg.h>
  627. X#include "rc.h"
  628. X#include "utils.h"
  629. X#include "input.h"
  630. X#include "nalloc.h"
  631. X#include "hash.h"
  632. X#include "lex.h"
  633. X#include "open.h"
  634. X#include "tree.h"
  635. X#include "glom.h"
  636. X#include "builtins.h"
  637. X#include "parse.h"
  638. X
  639. Xboolean dashdee, dashee, dashvee, dashex, dashell, dasheye, interactive;
  640. Xint rc_pid;
  641. X
  642. X#define REALLYNULL ((void *) 0) /* used to terminate a vararg list with NULL */
  643. X
  644. Xstatic void assigndefault(char *,...);
  645. X
  646. Xvoid main(int argc, char *argv[], char *envp[]) {
  647. X    extern int getopt(int, char **, char *);
  648. X    extern int optind;
  649. X    extern char *optarg;
  650. X    char *dashsee[2], pid[8], *dollarzero, *null[1];
  651. X    int c;
  652. X
  653. X    dashee = dashell = dashvee = dashex = dashdee = FALSE;
  654. X    dashsee[0] = dashsee[1] = NULL;
  655. X    dollarzero = argv[0];
  656. X
  657. X    dashell = (*argv[0] == '-'); /* Unix tradition */
  658. X
  659. X    while ((c = getopt(argc, argv, "leivdxc:")) != -1)
  660. X        switch (c) {
  661. X        case 'l':
  662. X            dashell = TRUE;
  663. X            break;
  664. X        case 'e':
  665. X            dashee = TRUE;
  666. X            break;
  667. X        case 'i':
  668. X            dasheye = interactive = TRUE;
  669. X            break;
  670. X        case 'v':
  671. X            dashvee = TRUE;
  672. X            break;
  673. X        case 'x':
  674. X            dashex = TRUE;
  675. X            break;
  676. X        case 'd':
  677. X            dashdee = TRUE;
  678. X            break;
  679. X        case 'c':
  680. X            dashsee[0] = optarg;
  681. X            goto quitopts;
  682. X        case '?':
  683. X            exit(1);
  684. X        }
  685. X
  686. Xquitopts:
  687. X    argv += optind;
  688. X
  689. X    /* use isatty() iff -i is not set, and iff the input is not from a script or -c flag */
  690. X    if (!dasheye && dashsee[0] == NULL && *argv == NULL)
  691. X        interactive = isatty(0);
  692. X
  693. X    inithandler();
  694. X    inithash();
  695. X    initparse();
  696. X    assigndefault("prompt", "; ", "", REALLYNULL);
  697. X    assigndefault("path", ".", "/bin", "/usr/bin", "/usr/ucb", REALLYNULL);
  698. X    assigndefault("ifs", " ", "\t", "\n", REALLYNULL);
  699. X    assigndefault("pid", sprint(pid, "%d", rc_pid = getpid()), REALLYNULL);
  700. X    initenv(envp);
  701. X    initinput();
  702. X    null[0] = NULL;
  703. X    starassign(dollarzero, null, FALSE); /* assign $0 to $* */
  704. X
  705. X    if (dashsee[0] != NULL) {    /* input from the -c flag? */
  706. X        if (*argv != NULL)
  707. X            starassign(dollarzero, argv, FALSE);
  708. X        pushinput(STRING, dashsee);
  709. X    } else if (*argv != NULL) {    /* else from a file? */
  710. X        b_dot(--argv);
  711. X        rc_exit(0);
  712. X    } else {            /* else stdin */
  713. X        pushinput(FD, 0);
  714. X    }
  715. X
  716. X    doit(TRUE);
  717. X    rc_exit(0);
  718. X}
  719. X
  720. Xstatic void assigndefault(char *name,...) {
  721. X    va_list ap;
  722. X    List *l;
  723. X    char *v;
  724. X
  725. X    va_start(ap, name);
  726. X
  727. X    for (l = NULL; (v = va_arg(ap, char *)) != NULL;)
  728. X        l = append(l, word(v, NULL));
  729. X
  730. X    varassign(name, l, FALSE);
  731. X
  732. X    if (streq(name,"path"))
  733. X        alias(name, l, FALSE);
  734. X
  735. X    va_end(ap);
  736. X}
  737. END_OF_FILE
  738.   if test 2456 -ne `wc -c <'main.c'`; then
  739.     echo shar: \"'main.c'\" unpacked with wrong size!
  740.   fi
  741.   # end of 'main.c'
  742. fi
  743. if test -f 'match.c' -a "${1}" != "-c" ; then 
  744.   echo shar: Will not clobber existing file \"'match.c'\"
  745. else
  746.   echo shar: Extracting \"'match.c'\" \(1992 characters\)
  747.   sed "s/^X//" >'match.c' <<'END_OF_FILE'
  748. X/* match.c: pattern matching routines */
  749. X
  750. X#include "rc.h"
  751. X#include "utils.h"
  752. X#include "match.h"
  753. X
  754. Xstatic int rangematch(char *, char);
  755. X
  756. X/*
  757. X   match() matches a single pattern against a single string.
  758. X*/
  759. X
  760. Xboolean match(char *p, char *m, char *s) {
  761. X    int i = 0;
  762. X    int j;
  763. X
  764. X    if (m == NULL)
  765. X        return streq(p, s);
  766. X
  767. X    while(1) {
  768. X        if (p[i] == '\0')
  769. X            return *s == '\0';
  770. X        else if (m[i]) {
  771. X            switch (p[i++]) {
  772. X            case '?':
  773. X                if (*s++ == '\0')
  774. X                    return FALSE;
  775. X                break;
  776. X            case '*':
  777. X                /* collapse multiple stars */
  778. X                while (p[i] == '*' && m[i] == 1)
  779. X                    i++;
  780. X
  781. X                /* star at end of pattern? */
  782. X                if (p[i] == '\0')
  783. X                    return TRUE;
  784. X
  785. X                while (*s != '\0')
  786. X                    if (match(p + i, m + i, s++))
  787. X                        return TRUE;
  788. X                return FALSE;
  789. X            case '[':
  790. X                if (*s == '\0' || ((j = rangematch(p + i, *s++)) < 0))
  791. X                    return FALSE;
  792. X                i += j;
  793. X                break;
  794. X            default:
  795. X                fprint(2,"%c is not a metacharacter\n", p[i-1]);
  796. X                return FALSE;
  797. X            }
  798. X        } else if (p[i++] != *s++) {
  799. X                return FALSE;
  800. X        }
  801. X    }
  802. X}
  803. X
  804. X/*
  805. X   From the ed(1) man pages (on ranges):
  806. X
  807. X    The `-' is treated as an ordinary character if it occurs first
  808. X    (or first after an initial ^) or last in the string.
  809. X
  810. X    The right square bracket does not terminate the enclosed string
  811. X    if it is the first character (after an initial `^', if any), in
  812. X    the bracketed string.
  813. X
  814. X   rangematch() matches a single character against a class, and returns
  815. X   an integer offset to the end of the range on success, or -1 on
  816. X   failure.
  817. X*/
  818. X
  819. Xstatic int rangematch(char *p, char c) {
  820. X    char *orig = p;
  821. X    boolean neg = (*p == '~');
  822. X    boolean matched = FALSE;
  823. X
  824. X    if (neg)
  825. X        p++;
  826. X
  827. X    if (*p == ']') {
  828. X        p++;
  829. X        matched = (c == ']');
  830. X    }
  831. X
  832. X    for (; *p != ']'; p++) {
  833. X        if (*p == '\0')
  834. X            return -1;    /* bad syntax */
  835. X        if (p[1] == '-' && p[2] != ']') { /* check for [..-..] but ignore [..-] */
  836. X            if (c >= *p)
  837. X                matched |= (c <= p[2]);
  838. X            p += 2;
  839. X        } else {
  840. X            matched |= (*p == c);
  841. X        }
  842. X    }
  843. X
  844. X    if (matched ^ neg)
  845. X        return p - orig + 1; /* skip the right-bracket */
  846. X    else
  847. X        return -1;
  848. X}
  849. X
  850. END_OF_FILE
  851.   if test 1992 -ne `wc -c <'match.c'`; then
  852.     echo shar: \"'match.c'\" unpacked with wrong size!
  853.   fi
  854.   # end of 'match.c'
  855. fi
  856. if test -f 'match.h' -a "${1}" != "-c" ; then 
  857.   echo shar: Will not clobber existing file \"'match.h'\"
  858. else
  859.   echo shar: Extracting \"'match.h'\" \(46 characters\)
  860.   sed "s/^X//" >'match.h' <<'END_OF_FILE'
  861. Xextern boolean match(char *, char *, char *);
  862. END_OF_FILE
  863.   if test 46 -ne `wc -c <'match.h'`; then
  864.     echo shar: \"'match.h'\" unpacked with wrong size!
  865.   fi
  866.   # end of 'match.h'
  867. fi
  868. if test -f 'mksignal' -a "${1}" != "-c" ; then 
  869.   echo shar: Will not clobber existing file \"'mksignal'\"
  870. else
  871.   echo shar: Extracting \"'mksignal'\" \(1683 characters\)
  872.   sed "s/^X//" >'mksignal' <<'END_OF_FILE'
  873. X#!/bin/sh
  874. X# generate rc's internal signal table from signal.h
  875. X
  876. Xexec > sigmsgs.c
  877. X
  878. Xecho 'char *signals[][2] = {'
  879. X
  880. Xsed '    s/\/\*[     ]*//
  881. X    s/[     ]*\*\///
  882. X    s/([@*+!]) //
  883. X    s/[     ]*([a-zA-Z,->& ]*)[     ]*//
  884. X    s/[     ]*signal$//' $1 |
  885. Xawk '
  886. X    BEGIN {
  887. X        # assign to nomesg["SIGNAME"] to suppress a long message
  888. X        nomesg["SIGINT"] = 1
  889. X        nomesg["SIGPIPE"] = 1
  890. X        # assign to mesg["SIGNAME"] to override a message
  891. X        mesg["SIGHUP"] = "hangup"
  892. X        mesg["SIGKILL"] = "killed"
  893. X        mesg["SIGQUIT"] = "quit"
  894. X        mesg["SIGTERM"] = "terminated"
  895. X        mesg["SIGURG"] = "urgent condition on i/o channel"
  896. X        mesg["SIGSTOP"] = "stop signal not from tty"
  897. X        mesg["SIGTSTP"] = "stopped"
  898. X        mesg["SIGCONT"] = "continue"
  899. X        mesg["SIGCHLD"] = "child stop or exit"
  900. X        mesg["SIGTTIN"] = "background tty read"
  901. X        mesg["SIGTTOU"] = "background tty write"
  902. X        # assign to ignore["SIGNAME"] to explicitly ignore a named signal
  903. X        ignore["SIGMAX"] = 1
  904. X    }
  905. X    $1 == "#define" && $2 == "NSIG" && $3 ~ /^[0-9]+$/ { nsig = $3 }
  906. X    $1 == "#define" && $2 ~ /^SIG/ && $3 ~ /^[0-9]+$/ && sig[$3] == "" && ignore[$2] == 0 {
  907. X        sig[$3] = $2
  908. X        if ($3 > max)
  909. X            max = $3
  910. X        if (mesg[$2] == "" && nomesg[$2] == 0) {
  911. X            str = $4
  912. X            for (i = 5; i <= NF; i++)
  913. X                str = str " " $i
  914. X            mesg[$2] = str
  915. X        }
  916. X    }
  917. X    END {
  918. X        if (nsig == 0)
  919. X            nsig = max + 1
  920. X        printf "    !!,        !!,\n"
  921. X        for (i = 1; i < nsig; i++) {
  922. X            if (sig[i] == "")
  923. X                printf "    !!,        !!,\n"
  924. X            else
  925. X                printf "    !%s!,    !%s!,\n", sig[i], mesg[sig[i]]
  926. X        }
  927. X    }
  928. X' |
  929. Xtr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ!' 'abcdefghijklmnopqrstuvwxyz"'
  930. X
  931. Xecho '};'
  932. X
  933. Xexec > sigmsgs.h
  934. X
  935. Xecho 'extern char *signals[][2];'
  936. X
  937. Xgrep '^    ' sigmsgs.c |        # the thing in quotes is ^<tab>
  938. Xawk '
  939. X        { sum = sum + 1; }
  940. X    END    { print "#define NUMOFSIGNALS", sum }
  941. X'
  942. END_OF_FILE
  943.   if test 1683 -ne `wc -c <'mksignal'`; then
  944.     echo shar: \"'mksignal'\" unpacked with wrong size!
  945.   fi
  946.   # end of 'mksignal'
  947. fi
  948. if test -f 'nalloc.c' -a "${1}" != "-c" ; then 
  949.   echo shar: Will not clobber existing file \"'nalloc.c'\"
  950. else
  951.   echo shar: Extracting \"'nalloc.c'\" \(2218 characters\)
  952.   sed "s/^X//" >'nalloc.c' <<'END_OF_FILE'
  953. X/* nalloc.c: a simple single-arena allocator for command-line-lifetime allocation */
  954. X
  955. X#include "rc.h"
  956. X#include "utils.h"
  957. X#include "nalloc.h"
  958. X
  959. Xstatic struct Block {
  960. X    SIZE_T used;
  961. X    SIZE_T size;
  962. X    char *mem;
  963. X    Block *n;
  964. X} *fl, *ul;
  965. X
  966. X/* alignto() works only with power of 2 blocks and assumes 2's complement arithmetic */
  967. X#define alignto(m, n)   ((m + n - 1) & ~(n - 1))
  968. X#define BLOCKSIZE 4096
  969. X
  970. X/* gets a block from malloc space and places it at the head of the used-list */
  971. X
  972. Xstatic void getblock(SIZE_T n) {
  973. X    Block *r, *p;
  974. X
  975. X    for (r = fl, p = NULL; r != NULL; p = r, r = r->n)
  976. X        if (n <= r->size)
  977. X            break;
  978. X
  979. X    if (r != NULL) {
  980. X        if (p != NULL)
  981. X            p->n = r->n;
  982. X        else
  983. X            fl = r->n;
  984. X    } else {
  985. X        r = enew(Block);
  986. X        r->mem = ealloc(alignto(n, BLOCKSIZE));
  987. X        r->size = alignto(n, BLOCKSIZE);
  988. X    }
  989. X
  990. X    r->used = 0;
  991. X    r->n = ul;
  992. X    ul = r;
  993. X}
  994. X
  995. X/*
  996. X   A fast single-arena allocator. Looks at the current block, and if there is not enough room,
  997. X   it goes to getblock() for more. "ul" stands for "used list", and the head of the list is the
  998. X   current block.
  999. X*/
  1000. X
  1001. Xvoid *nalloc(SIZE_T n) {
  1002. X    char *ret;
  1003. X
  1004. X        n = alignto(n, sizeof (ALIGN_T));
  1005. X
  1006. X    if (ul == NULL || n + ul->used >= ul->size)
  1007. X        getblock(n);
  1008. X
  1009. X    ret = ul->mem + ul->used;
  1010. X    ul->used += n;
  1011. X    return ret;
  1012. X}
  1013. X
  1014. X/*
  1015. X   Frees memory from nalloc space by putting it on the freelist. Returns free blocks to the
  1016. X   system, retaining at least MAXMEM bytes worth of blocks for nalloc.
  1017. X*/
  1018. X
  1019. X#define MAXMEM 500000
  1020. X
  1021. Xvoid nfree() {
  1022. X    Block *r;
  1023. X    SIZE_T count;
  1024. X
  1025. X    if (ul == NULL)
  1026. X        return;
  1027. X
  1028. X    for (r = ul; r->n != NULL; r = r->n)
  1029. X        ;
  1030. X
  1031. X    r->n = fl;
  1032. X    fl = ul;
  1033. X    ul = NULL;
  1034. X
  1035. X    for (r = fl, count = r->size; r->n != NULL; r = r->n, count += r->size) {
  1036. X        if (count >= MAXMEM) {
  1037. X            Block *tmp = r;
  1038. X
  1039. X            r = r->n;
  1040. X            tmp->n = NULL;        /* terminate the freelist */
  1041. X
  1042. X            while (r != NULL) {    /* free memory off the tail of the freelist */
  1043. X                tmp = r->n;
  1044. X                efree(r->mem);
  1045. X                efree(r);
  1046. X                r = tmp;
  1047. X            }
  1048. X        return;
  1049. X        }
  1050. X    }
  1051. X}
  1052. X
  1053. X/*
  1054. X   "allocates" a new arena by zeroing out the old one. Up to the calling routine to keep
  1055. X   the old value of the block around.
  1056. X*/
  1057. X
  1058. XBlock *newblock() {
  1059. X    Block *ret = ul;
  1060. X
  1061. X    ul = NULL;
  1062. X    return ret;
  1063. X}
  1064. X
  1065. X/* "restores" an arena to its saved value. */
  1066. X
  1067. Xvoid restoreblock(Block *b) {
  1068. X    nfree();
  1069. X    ul = b;
  1070. X}
  1071. END_OF_FILE
  1072.   if test 2218 -ne `wc -c <'nalloc.c'`; then
  1073.     echo shar: \"'nalloc.c'\" unpacked with wrong size!
  1074.   fi
  1075.   # end of 'nalloc.c'
  1076. fi
  1077. if test -f 'nalloc.h' -a "${1}" != "-c" ; then 
  1078.   echo shar: Will not clobber existing file \"'nalloc.h'\"
  1079. else
  1080.   echo shar: Extracting \"'nalloc.h'\" \(323 characters\)
  1081.   sed "s/^X//" >'nalloc.h' <<'END_OF_FILE'
  1082. Xextern Block *newblock(void);
  1083. Xextern void *nalloc(SIZE_T);
  1084. Xextern void nfree(void);
  1085. Xextern void restoreblock(Block *);
  1086. X
  1087. X#undef offsetof
  1088. X#define offsetof(t, m) ((SIZE_T) &((t *)0)->m)
  1089. X
  1090. X/* memory allocation abbreviation */
  1091. X#define nnew(x) ((x *) nalloc(sizeof(x)))
  1092. X#define ncpy(x) (strcpy((char *) nalloc(strlen(x) + 1), x))
  1093. END_OF_FILE
  1094.   if test 323 -ne `wc -c <'nalloc.h'`; then
  1095.     echo shar: \"'nalloc.h'\" unpacked with wrong size!
  1096.   fi
  1097.   # end of 'nalloc.h'
  1098. fi
  1099. if test -f 'node.h' -a "${1}" != "-c" ; then 
  1100.   echo shar: Will not clobber existing file \"'node.h'\"
  1101. else
  1102.   echo shar: Extracting \"'node.h'\" \(356 characters\)
  1103.   sed "s/^X//" >'node.h' <<'END_OF_FILE'
  1104. Xenum nodetype {
  1105. X    rANDAND, ASSIGN, BACKQ, rBANG, BODY, NOWAIT, BRACE, CONCAT,
  1106. X    rCOUNT, rELSE, rFLAT, rDUP, EPILOG, NEWFN, FORIN, rIF,
  1107. X    rOROR, rPIPE, PRE, rREDIR, RMFN, ARGS, rSUBSHELL,
  1108. X    rSWITCH, MATCH, VAR, VARSUB, rWHILE, rWORD, LAPPEND, NMPIPE
  1109. X};
  1110. X
  1111. Xtypedef struct Node Node;
  1112. X
  1113. Xstruct Node {
  1114. X    enum nodetype type;
  1115. X    union { char *s; int i; Node *p; } u[3];
  1116. X};
  1117. END_OF_FILE
  1118.   if test 356 -ne `wc -c <'node.h'`; then
  1119.     echo shar: \"'node.h'\" unpacked with wrong size!
  1120.   fi
  1121.   # end of 'node.h'
  1122. fi
  1123. if test -f 'open.c' -a "${1}" != "-c" ; then 
  1124.   echo shar: Will not clobber existing file \"'open.c'\"
  1125. else
  1126.   echo shar: Extracting \"'open.c'\" \(772 characters\)
  1127.   sed "s/^X//" >'open.c' <<'END_OF_FILE'
  1128. X/* open.c: to insulate <fcntl.h> from the rest of rc. */
  1129. X
  1130. X#include <fcntl.h>
  1131. X#include "lex.h"
  1132. X#include "open.h"
  1133. X
  1134. X/* prototype for open() follows. comment out if necessary */
  1135. X
  1136. X/*extern int open(const char *, int,...);*/
  1137. Xextern void rc_error(const char *);
  1138. X
  1139. X/*
  1140. X   Opens a file with the necessary flags. Assumes the following
  1141. X   declaration for enum redirtype:
  1142. X
  1143. X    enum redirtype {
  1144. X        FROM, CREATE, APPEND, HEREDOC, HERESTRING
  1145. X    };
  1146. X*/
  1147. X
  1148. Xstatic const int mode_masks[] = {
  1149. X    /* read */    O_RDONLY,
  1150. X    /* create */    O_TRUNC | O_CREAT | O_WRONLY,
  1151. X    /* append */    O_APPEND | O_CREAT | O_WRONLY
  1152. X};
  1153. X
  1154. Xint rc_open(const char *name, enum redirtype m) {
  1155. X    if ((unsigned int) m >= (sizeof(mode_masks)/sizeof(int)))
  1156. X        rc_error("bad mode passed to rc_open");
  1157. X
  1158. X    return open(name, mode_masks[m], 0644);
  1159. X}
  1160. END_OF_FILE
  1161.   if test 772 -ne `wc -c <'open.c'`; then
  1162.     echo shar: \"'open.c'\" unpacked with wrong size!
  1163.   fi
  1164.   # end of 'open.c'
  1165. fi
  1166. if test -f 'open.h' -a "${1}" != "-c" ; then 
  1167.   echo shar: Will not clobber existing file \"'open.h'\"
  1168. else
  1169.   echo shar: Extracting \"'open.h'\" \(50 characters\)
  1170.   sed "s/^X//" >'open.h' <<'END_OF_FILE'
  1171. Xextern int rc_open(const char *, enum redirtype);
  1172. END_OF_FILE
  1173.   if test 50 -ne `wc -c <'open.h'`; then
  1174.     echo shar: \"'open.h'\" unpacked with wrong size!
  1175.   fi
  1176.   # end of 'open.h'
  1177. fi
  1178. if test -f 'parse.h' -a "${1}" != "-c" ; then 
  1179.   echo shar: Will not clobber existing file \"'parse.h'\"
  1180. else
  1181.   echo shar: Extracting \"'parse.h'\" \(79 characters\)
  1182.   sed "s/^X//" >'parse.h' <<'END_OF_FILE'
  1183. Xextern Node *parsetree;
  1184. Xextern int yyparse(void);
  1185. Xextern void initparse(void);
  1186. END_OF_FILE
  1187.   if test 79 -ne `wc -c <'parse.h'`; then
  1188.     echo shar: \"'parse.h'\" unpacked with wrong size!
  1189.   fi
  1190.   # end of 'parse.h'
  1191. fi
  1192. if test -f 'rc.h' -a "${1}" != "-c" ; then 
  1193.   echo shar: Will not clobber existing file \"'rc.h'\"
  1194. else
  1195.   echo shar: Extracting \"'rc.h'\" \(603 characters\)
  1196.   sed "s/^X//" >'rc.h' <<'END_OF_FILE'
  1197. X#include "stddef.h"
  1198. X#include "stdlib.h"
  1199. X#include "string.h"
  1200. X#include "unistd.h"
  1201. X
  1202. X#include "node.h"
  1203. X
  1204. X/* braindamaged IBM header files #define true and false */
  1205. X#undef FALSE
  1206. X#undef TRUE
  1207. X
  1208. Xenum bool { FALSE, TRUE };
  1209. X
  1210. Xtypedef enum bool boolean;
  1211. Xtypedef struct Rq Rq;
  1212. Xtypedef struct Block Block;
  1213. Xtypedef struct List List;
  1214. X
  1215. Xstruct List {
  1216. X    char *w;
  1217. X    char *m;
  1218. X    List *n;
  1219. X};
  1220. X
  1221. Xextern char *prompt, *prompt2;
  1222. Xextern Rq *redirq;
  1223. Xextern boolean dashdee, dashee, dashvee, dashex, dashell, dasheye, interactive;
  1224. Xextern int rc_pid;
  1225. Xextern int lineno;
  1226. Xextern List *fifoq;
  1227. X
  1228. X#define arraysize(a) ((int)sizeof(a)/sizeof(*a))
  1229. END_OF_FILE
  1230.   if test 603 -ne `wc -c <'rc.h'`; then
  1231.     echo shar: \"'rc.h'\" unpacked with wrong size!
  1232.   fi
  1233.   # end of 'rc.h'
  1234. fi
  1235. if test -f 'redir.h' -a "${1}" != "-c" ; then 
  1236.   echo shar: Will not clobber existing file \"'redir.h'\"
  1237. else
  1238.   echo shar: Extracting \"'redir.h'\" \(28 characters\)
  1239.   sed "s/^X//" >'redir.h' <<'END_OF_FILE'
  1240. Xextern void doredirs(void);
  1241. END_OF_FILE
  1242.   if test 28 -ne `wc -c <'redir.h'`; then
  1243.     echo shar: \"'redir.h'\" unpacked with wrong size!
  1244.   fi
  1245.   # end of 'redir.h'
  1246. fi
  1247. if test -f 'status.c' -a "${1}" != "-c" ; then 
  1248.   echo shar: Will not clobber existing file \"'status.c'\"
  1249. else
  1250.   echo shar: Extracting \"'status.c'\" \(2375 characters\)
  1251.   sed "s/^X//" >'status.c' <<'END_OF_FILE'
  1252. X/* status.c: functions for printing fancy status messages in rc */
  1253. X
  1254. X#include "rc.h"
  1255. X#include "utils.h"
  1256. X#include "status.h"
  1257. X#include "nalloc.h"
  1258. X#include "walk.h"
  1259. X#include "sigmsgs.h"
  1260. X
  1261. X/* status == the wait() value of the last command in the pipeline, or the last command */
  1262. X
  1263. Xstatic int statuses[512];
  1264. Xstatic int pipelength = 1;
  1265. X
  1266. X/*
  1267. X   Test to see if rc's status is true. According to td, status is true if and only if every
  1268. X   pipe-member has an exit status of zero.
  1269. X*/
  1270. X
  1271. Xint istrue(void) {
  1272. X    int i;
  1273. X
  1274. X    for (i = 0; i < pipelength; i++)
  1275. X        if (statuses[i] != 0)
  1276. X            return FALSE;
  1277. X    return TRUE;
  1278. X}
  1279. X
  1280. X/*
  1281. X   Return the status as an integer. A status which has low-bits set is a signal number,
  1282. X   whereas a status with high bits set is a value set from exit().
  1283. X*/
  1284. X
  1285. Xint getstatus(void) {
  1286. X    int s = statuses[0];
  1287. X
  1288. X    return s & 0xff ? s & 0x7f : (s >> 8) & 0xff;
  1289. X}
  1290. X
  1291. Xvoid set(boolean code) {
  1292. X    setstatus((!code) << 8); /* exit status 1 == 0x100 */
  1293. X}
  1294. X
  1295. X/* take a pipeline and store the exit statuses. Check to see whether any of the children dumped core */
  1296. X
  1297. Xvoid setpipestatus(int stats[], int num) {
  1298. X    int i;
  1299. X
  1300. X    for (i = 0; i < (pipelength = num); i++) {
  1301. X        statprint(stats[i]);
  1302. X        statuses[i] = stats[i];
  1303. X    }
  1304. X}
  1305. X
  1306. X/* set a simple status, as opposed to a pipeline */
  1307. X
  1308. Xvoid setstatus(int i) {
  1309. X    pipelength = 1;
  1310. X    statuses[0] = i;
  1311. X    statprint(i);
  1312. X}
  1313. X
  1314. X/* print a message if termination was with a signal, and if the child dumped core. exit on error if -e is set */
  1315. X
  1316. Xvoid statprint(int i) {
  1317. X    if (i & 0xff) {
  1318. X        char *msg = ((i & 0x7f) < NUMOFSIGNALS ? signals[i & 0x7f][1] : "");
  1319. X
  1320. X        if (i & 0x80) {
  1321. X            if (*msg == '\0')
  1322. X                fprint(2,"core dumped\n");
  1323. X            else
  1324. X                fprint(2,"%s--core dumped\n",msg);
  1325. X        } else if (*msg != '\0')
  1326. X            fprint(2,"%s\n",msg);
  1327. X    }
  1328. X
  1329. X    if (i != 0 && dashee && !cond)
  1330. X        rc_exit(getstatus());
  1331. X}
  1332. X
  1333. X/* prepare a list to be passed back. Used whenever $status is dereferenced */
  1334. X
  1335. XList *sgetstatus(void) {
  1336. X    List *r;
  1337. X    int i;
  1338. X
  1339. X    for (r = NULL, i = 0; i < pipelength; i++) {
  1340. X        char buf[16];
  1341. X        List *q = nnew(List);
  1342. X        int s = statuses[i];
  1343. X        int t;
  1344. X
  1345. X        q->n = r;
  1346. X        r = q;
  1347. X
  1348. X        if ((t = s & 0x7f) != 0) {
  1349. X            if (t < NUMOFSIGNALS && *signals[t][0] != '\0')
  1350. X                sprint(buf, "%s", signals[t][0]);
  1351. X            else
  1352. X                sprint(buf,"-%d", t); /* unknown signals are negated */
  1353. X            if (s & 0x80)
  1354. X                strcat(buf, "+core");
  1355. X        } else {
  1356. X            sprint(buf, "%d", (s >> 8) & 0xff);
  1357. X        }
  1358. X
  1359. X        r->w = ncpy(buf);
  1360. X        r->m = NULL;
  1361. X    }
  1362. X
  1363. X    return r;
  1364. X}
  1365. END_OF_FILE
  1366.   if test 2375 -ne `wc -c <'status.c'`; then
  1367.     echo shar: \"'status.c'\" unpacked with wrong size!
  1368.   fi
  1369.   # end of 'status.c'
  1370. fi
  1371. if test -f 'status.h' -a "${1}" != "-c" ; then 
  1372.   echo shar: Will not clobber existing file \"'status.h'\"
  1373. else
  1374.   echo shar: Extracting \"'status.h'\" \(206 characters\)
  1375.   sed "s/^X//" >'status.h' <<'END_OF_FILE'
  1376. Xextern int istrue(void);
  1377. Xextern int getstatus(void);
  1378. Xextern void set(boolean);
  1379. Xextern void setstatus(int);
  1380. Xextern List *sgetstatus(void);
  1381. Xextern void setpipestatus(int [], int);
  1382. Xextern void statprint(int);
  1383. END_OF_FILE
  1384.   if test 206 -ne `wc -c <'status.h'`; then
  1385.     echo shar: \"'status.h'\" unpacked with wrong size!
  1386.   fi
  1387.   # end of 'status.h'
  1388. fi
  1389. if test -f 'stddef.h' -a "${1}" != "-c" ; then 
  1390.   echo shar: Will not clobber existing file \"'stddef.h'\"
  1391. else
  1392.   echo shar: Extracting \"'stddef.h'\" \(758 characters\)
  1393.   sed "s/^X//" >'stddef.h' <<'END_OF_FILE'
  1394. X/* stddef.h
  1395. X    This file provides a definition for size_t and align_t that
  1396. X    should work for your system. If it does not, it is up to you to
  1397. X    make it the right thing. The problem is that I cannot rely upon
  1398. X    <sys/params.h> to do the right thing on machines which don't
  1399. X    yet have ansi header files. Note that on many RISC machines,
  1400. X    align_t must be at least 32 bits wide, and sparc doubles are
  1401. X    aligned on 64 bit boundaries, but of course, rc does not use
  1402. X    doubles in its code, so the "typedef long ALIGN_T" is good
  1403. X    enough in the sparc's case. Also for performance reasons on a
  1404. X    VAX one would probably want align_t to be 32 bits wide.
  1405. X*/
  1406. Xtypedef long ALIGN_T;
  1407. Xtypedef unsigned int SIZE_T;
  1408. Xtypedef short int MODE_T;
  1409. Xtypedef int PID_T;
  1410. X
  1411. X#undef NULL
  1412. X#define NULL 0
  1413. END_OF_FILE
  1414.   if test 758 -ne `wc -c <'stddef.h'`; then
  1415.     echo shar: \"'stddef.h'\" unpacked with wrong size!
  1416.   fi
  1417.   # end of 'stddef.h'
  1418. fi
  1419. if test -f 'stdlib.h' -a "${1}" != "-c" ; then 
  1420.   echo shar: Will not clobber existing file \"'stdlib.h'\"
  1421. else
  1422.   echo shar: Extracting \"'stdlib.h'\" \(462 characters\)
  1423.   sed "s/^X//" >'stdlib.h' <<'END_OF_FILE'
  1424. X/*
  1425. X   stdlib.h function prototypes as taken from Appendix B of K&R 2.
  1426. X   Unused functions are:
  1427. X    atof(), atoi(), atol(), strtod(), strtol(), strtoul(), rand(),
  1428. X    srand(), calloc(), abort(), atexit(), system(), getenv(), bsearch(),
  1429. X    abs(), labs(), div() and ldiv()
  1430. X*/
  1431. X
  1432. Xextern void *malloc(SIZE_T);
  1433. Xextern void *realloc(void *, SIZE_T);
  1434. Xextern void free(void *);
  1435. Xextern void exit(int);
  1436. Xextern void qsort(void *, SIZE_T, SIZE_T, int (*)(const void *, const void *));
  1437. END_OF_FILE
  1438.   if test 462 -ne `wc -c <'stdlib.h'`; then
  1439.     echo shar: \"'stdlib.h'\" unpacked with wrong size!
  1440.   fi
  1441.   # end of 'stdlib.h'
  1442. fi
  1443. if test -f 'string.h' -a "${1}" != "-c" ; then 
  1444.   echo shar: Will not clobber existing file \"'string.h'\"
  1445. else
  1446.   echo shar: Extracting \"'string.h'\" \(475 characters\)
  1447.   sed "s/^X//" >'string.h' <<'END_OF_FILE'
  1448. Xextern int strncmp(const char *, const char *, SIZE_T);
  1449. Xextern int strcmp(const char *, const char *);
  1450. Xextern SIZE_T strlen(const char *);
  1451. Xextern char *strchr(const char *, int);
  1452. Xextern char *strcpy(char *, const char *);
  1453. Xextern char *strncpy(char *, const char *, SIZE_T);
  1454. Xextern char *strcat(char *, const char *);
  1455. Xextern char *strncat(char *, const char *, SIZE_T);
  1456. Xextern void *memcpy(void *, const void *, SIZE_T);
  1457. X
  1458. X#define streq(x,y) (*(x) == *(y) && strcmp(x,y) == 0)
  1459. END_OF_FILE
  1460.   if test 475 -ne `wc -c <'string.h'`; then
  1461.     echo shar: \"'string.h'\" unpacked with wrong size!
  1462.   fi
  1463.   # end of 'string.h'
  1464. fi
  1465. if test -f 'tree.h' -a "${1}" != "-c" ; then 
  1466.   echo shar: Will not clobber existing file \"'tree.h'\"
  1467. else
  1468.   echo shar: Extracting \"'tree.h'\" \(132 characters\)
  1469.   sed "s/^X//" >'tree.h' <<'END_OF_FILE'
  1470. Xextern Node *newnode(int /*enum nodetype*/ t,...);
  1471. Xextern Node *treecpy(Node *s, void *(*)(SIZE_T));
  1472. Xextern void treefree(Node *s);
  1473. END_OF_FILE
  1474.   if test 132 -ne `wc -c <'tree.h'`; then
  1475.     echo shar: \"'tree.h'\" unpacked with wrong size!
  1476.   fi
  1477.   # end of 'tree.h'
  1478. fi
  1479. if test -f 'unistd.h' -a "${1}" != "-c" ; then 
  1480.   echo shar: Will not clobber existing file \"'unistd.h'\"
  1481. else
  1482.   echo shar: Extracting \"'unistd.h'\" \(490 characters\)
  1483.   sed "s/^X//" >'unistd.h' <<'END_OF_FILE'
  1484. Xextern PID_T fork(void);
  1485. Xextern PID_T getpid(void);
  1486. Xextern int chdir(const char *);
  1487. Xextern int close(int);
  1488. Xextern int dup2(int, int);
  1489. Xextern int execve(const char *, const char **, const char **);
  1490. Xextern int isatty(int);
  1491. Xextern int mknod(const char *, int, int);
  1492. Xextern int pipe(int *);
  1493. Xextern int read(int, void *, unsigned int);
  1494. Xextern int setpgrp(int, PID_T);
  1495. Xextern int unlink(const char *);
  1496. Xextern int write(int, const void *, unsigned int);
  1497. Xextern int wait(int *);
  1498. X
  1499. Xextern int errno;
  1500. END_OF_FILE
  1501.   if test 490 -ne `wc -c <'unistd.h'`; then
  1502.     echo shar: \"'unistd.h'\" unpacked with wrong size!
  1503.   fi
  1504.   # end of 'unistd.h'
  1505. fi
  1506. if test -f 'utils.h' -a "${1}" != "-c" ; then 
  1507.   echo shar: Will not clobber existing file \"'utils.h'\"
  1508. else
  1509.   echo shar: Extracting \"'utils.h'\" \(854 characters\)
  1510.   sed "s/^X//" >'utils.h' <<'END_OF_FILE'
  1511. Xextern char *strprint(char *, int, int);
  1512. Xextern char *sprint(char *, char *,...);
  1513. Xextern int isabsolute(char *); /* not boolean because y.tab.c includes utils.h */
  1514. Xextern int a2u(char *);
  1515. Xextern int o2u(char *);
  1516. Xextern int starstrcmp(const void *, const void *);
  1517. Xextern void *ealloc(SIZE_T);
  1518. Xextern void *erealloc(void *, SIZE_T);
  1519. Xextern void efree(void *);
  1520. Xextern void fprint(int, char *,...);
  1521. Xextern void empty_fifoq(void);
  1522. Xextern void rc_error(char *);
  1523. Xextern void rc_exit(int); /* prototyped here, but defined in fn.c */
  1524. Xextern void sig(int);
  1525. Xextern void clear(char *, SIZE_T);
  1526. Xextern void uerror(char *);
  1527. Xextern void writeall(int, char *, SIZE_T);
  1528. Xextern SIZE_T strarraylen(char **);
  1529. X
  1530. X/* memory allocation abbreviations */
  1531. X#define enew(x) ((x *) ealloc(sizeof(x)))
  1532. X#define ecpy(x) strcpy((char *) ealloc(strlen(x) + 1),x)
  1533. X
  1534. X#define FPRINT_SIZE 16384
  1535. END_OF_FILE
  1536.   if test 854 -ne `wc -c <'utils.h'`; then
  1537.     echo shar: \"'utils.h'\" unpacked with wrong size!
  1538.   fi
  1539.   # end of 'utils.h'
  1540. fi
  1541. if test -f 'version.c' -a "${1}" != "-c" ; then 
  1542.   echo shar: Will not clobber existing file \"'version.c'\"
  1543. else
  1544.   echo shar: Extracting \"'version.c'\" \(63 characters\)
  1545.   sed "s/^X//" >'version.c' <<'END_OF_FILE'
  1546. Xstatic volatile const char *id = "rc version 1.0, 5/20/91.\n";
  1547. END_OF_FILE
  1548.   if test 63 -ne `wc -c <'version.c'`; then
  1549.     echo shar: \"'version.c'\" unpacked with wrong size!
  1550.   fi
  1551.   # end of 'version.c'
  1552. fi
  1553. if test -f 'walk.h' -a "${1}" != "-c" ; then 
  1554.   echo shar: Will not clobber existing file \"'walk.h'\"
  1555. else
  1556.   echo shar: Extracting \"'walk.h'\" \(59 characters\)
  1557.   sed "s/^X//" >'walk.h' <<'END_OF_FILE'
  1558. Xextern boolean walk(Node *, boolean);
  1559. Xextern boolean cond;
  1560. END_OF_FILE
  1561.   if test 59 -ne `wc -c <'walk.h'`; then
  1562.     echo shar: \"'walk.h'\" unpacked with wrong size!
  1563.   fi
  1564.   # end of 'walk.h'
  1565. fi
  1566. echo shar: End of archive 4 \(of 4\).
  1567. cp /dev/null ark4isdone
  1568. MISSING=""
  1569. for I in 1 2 3 4 ; do
  1570.     if test ! -f ark${I}isdone ; then
  1571.     MISSING="${MISSING} ${I}"
  1572.     fi
  1573. done
  1574. if test "${MISSING}" = "" ; then
  1575.     echo You have unpacked all 4 archives.
  1576.     rm -f ark[1-9]isdone
  1577. else
  1578.     echo You still must unpack the following archives:
  1579.     echo "        " ${MISSING}
  1580. fi
  1581. exit 0
  1582. exit 0 # Just in case...
  1583. -- 
  1584. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  1585. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  1586. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  1587. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  1588.